/*
 * \brief  Core-specific instance of the CPU session/thread interfaces
 * \author Christian Helmuth
 * \date   2006-07-17
 */

/*
 * Copyright (C) 2006-2009 Christian Helmuth
 * Genode Labs, Feske & Helmuth Systementwicklung GbR
 *
 * This file is part of the Genode OS framework, which is distributed
 * under the terms of the GNU General Public License version 2.
 */

#ifndef _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_
#define _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_

/* Genode */
#include <util/list.h>
#include <base/tslab.h>
#include <base/lock.h>
#include <cpu_session/server.h>

/* Core */
#include <platform.h>

namespace Genode {

	/*
	 * We make Cpu_thread a server object only to be able
	 * to use the 'Capability' -> 'Server_object' lookup
	 * functionality of an entry point. It does not provide
	 * a RPC interface.
	 */
	class Cpu_thread : public Server_object,
	                   public List<Cpu_thread>::Element
	{
		private:

			Platform_thread _platform_thread;

			bool            _bound;            /* pd binding flag */

		public:

			Cpu_thread(const char *name)
			: _platform_thread(name), _bound(false) { }


			/************************
			 ** Accessor functions **
			 ************************/

			inline Platform_thread * platform_thread() { return &_platform_thread; }
			inline bool bound() const                  { return _bound; }
			inline void bound(bool b)                  { _bound = b; }


			/*****************************
			 ** Server object interface **
			 ****************************/

			int dispatch(int op, Ipc_istream &is, Ipc_ostream &os) { return 0; }
	};


	class Cpu_session_component : public Cpu_session_server
	{
		private:

			Server_entrypoint      *_thread_ep;
			Tslab<Cpu_thread, 1024> _slab;              /* meta-data allocator */
			Lock                    _slab_lock;         /* protect slab access */
			List<Cpu_thread>        _thread_list;
			Lock                    _thread_list_lock;  /* protect thread list */

			/**
			 * Lookup thread in CPU session by its capability
			 *
			 * \retval NULL  thread capability is invalid or
			 *               does not belong to the CPU session
			 */
			Cpu_thread *_lookup_thread(Thread_capability thread) {
				return dynamic_cast<Cpu_thread *>
				       (_thread_ep->obj_by_cap(thread)); }

			/**
			 * Raw thread-killing functionality
			 *
			 * This function is called from the 'kill_thread' function and
			 * the destructor. Each these functions grab the list lock
			 * by themselves and call this function to perform the actual
			 * killing.
			 */
			void _unsynchronized_kill_thread(Cpu_thread *thread);

		public:

			/**
			 * Constructor
			 */
			Cpu_session_component(Server_entrypoint *thread_ep,
			                      Allocator *md_alloc)
			: _thread_ep(thread_ep), _slab(md_alloc) { }

			/**
			 * Destructor
			 */
			~Cpu_session_component();


			/***************************
			 ** CPU session interface **
			 ***************************/

			Thread_capability create_thread(const char *);
			void kill_thread(Thread_capability);
			Thread_capability first();
			Thread_capability next(Thread_capability);
			int set_pager(Thread_capability, Thread_capability);
			int start(Thread_capability, addr_t, addr_t);
			void cancel_blocking(Thread_capability);
			int name(Thread_capability, char *, size_t);
			int state(Thread_capability, Thread_state *);
	};
}

#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */
